package com.honor.games.wg.services;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.badlogic.gdx.math.Vector2;

import static com.google.common.base.Preconditions.*;

import com.honor.games.wg.config.ApplicationConfiguration;
import com.honor.games.wg.entities.WGBoard;
import com.honor.games.wg.entities.WGCoordinates;
import com.honor.games.wg.entities.WGPlayer;
import com.honor.games.wg.entities.WGPlayerType;
import com.honor.games.wg.entities.WGTile;
import com.honor.games.wg.entities.WGUnit;
import com.honor.games.wg.entities.WGUnitType;
import com.honor.games.wg.entities.WGWorld;

@Service
public class WGWorldServices {

	private static Logger logger = LoggerFactory.getLogger(WGDebugConsoleService.class);

	@Autowired
	private ApplicationConfiguration config;

	@Autowired
	private WGGraphicsServices graphicsServices;

	@Autowired
	private WGMathServices mathServices;

	@Autowired
	private WGWorld world;

	public void createUnit(WGUnitType unitType, WGPlayerType playerType, int locationX, int locationY) {
		
		checkArgument(locationX >= 0 && locationY >= 0 && locationX < config.getBoardTilesWidthNumber() && locationY < config.getBoardTilesHeightNumber(),
				"x and y must be between the board bounds. x, y >= 0, x <= %s, y <= %s", config.getBoardTilesWidthNumber() - 1,
				config.getBoardTilesHeightNumber() - 1);
		checkArgument(!unitExists(locationX, locationY), "A unit already exists at %s, %s", locationX, locationY);
		
		logger.trace("Create unit - START ({}, {}, {}, {})", new Object[] { unitType, playerType, locationX, locationY });
		
		WGUnit unit = new WGUnit(unitType, getPlayerFromPlayerType(playerType), locationX, locationY);
		world.getUnits().add(unit);
		world.getBoard().getTiles()[locationY][locationX].setUnit(unit);

		Vector2 position = mathServices.calculateRealCoordinates(locationX, locationY);
		logger.trace("Calculated position for location in tiles {}, {} => {}, {} in real coordinates", new Object[] { locationX, locationY,
				position.x, position.y });
		graphicsServices.addUnit(unit, position.x, position.y);

		logger.trace("Create unit - STOP ({}, {}, {}, {})", new Object[] { unitType, playerType, locationX, locationY });
	}

	private WGPlayer getPlayerFromPlayerType(WGPlayerType playerType) {
		switch (playerType) {
		case PLAYER1:
			return world.getPlayer1();

		case PLAYER2:
			return world.getPlayer2();
		}

		return world.getPlayer1();
	}
	
	public boolean unitExists(int locationX, int locationY) {
		checkArgument(locationX >= 0 && locationY >= 0 && locationX < config.getBoardTilesWidthNumber() && locationY < config.getBoardTilesHeightNumber(),
				"x and y must be between the board bounds. x, y >= 0, x <= %s, y <= %s", config.getBoardTilesWidthNumber() - 1,
				config.getBoardTilesHeightNumber() - 1);
		
		return !world.getBoard().getTiles()[locationY][locationX].isEmpty();
	}
	
	public WGTile getTile(int locationX, int locationY) {
		checkArgument(locationX >= 0 && locationY >= 0 && locationX < config.getBoardTilesWidthNumber() && locationY < config.getBoardTilesHeightNumber(),
				"x and y must be between the board bounds. x, y >= 0, x <= %s, y <= %s", config.getBoardTilesWidthNumber() - 1,
				config.getBoardTilesHeightNumber() - 1);
		
		return world.getBoard().getTiles()[locationY][locationX];
	}
	
	public WGBoard getBoard() {
		return world.getBoard();
	}
}
